package dbutil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Types;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import annotation.Column;
import annotation.Id;
import annotation.Table;
import jdbc.OracleDriver;

public class Mapper {
	
	public <T> T loadById(Class<T> c, Object id) throws Exception {
		String sql = "";
		
		// 处理Table注解，组装from部分
		Table tableAnnotation = c.getAnnotation(Table.class);
		if (tableAnnotation == null) {
			throw new RuntimeException();
		}
		String tableName = tableAnnotation.tableName();
		if ("className".equals(tableName)) {
			tableName = c.getName();
		}
		sql = " from " + tableName;
		
		String selectColumns = "";
		for (Field field : c.getDeclaredFields()) {
			// 处理id注解，组装where条件
			Id idAnnotation = field.getAnnotation(Id.class);
			if (idAnnotation != null) {
				Column idColumnAnnotation = field.getAnnotation(Column.class);
				if (idColumnAnnotation == null) {
					throw new RuntimeException();
				}
				String idColumnName = idColumnAnnotation.name();
				if ("fieldName".equals(idColumnName)) {
					idColumnName = field.getName();
				}
				sql += " where " + idColumnName + " = " + id;
			}	
			
			// 处理Column注解，组装select部分
			Column columnAnnotation = field.getAnnotation(Column.class);
			if (columnAnnotation != null) {
				String columnName = columnAnnotation.name();
				if ("fieldName".equals(columnName)) {
					columnName = field.getName();
				}
				selectColumns += "," + columnName;
			}
		}
		if (selectColumns.length() == 0) {
			throw new RuntimeException();
		}
		selectColumns = selectColumns.substring(1);
		sql = "select " + selectColumns + sql;
		List<Map<String, Object>> list = OracleDriver.executeQuery(sql);
		if (list.isEmpty()) {
			return null;
		}
		Map<String, Object> map = list.get(0);
		T t = c.newInstance();
		for (Field field : c.getDeclaredFields()) {
			Column columnAnnotation = field.getAnnotation(Column.class);
			if (columnAnnotation != null) {
				String fieldName = field.getName();
				String columnName = columnAnnotation.name();
				if ("fieldName".equals(columnName)) {
					columnName = fieldName;
				}
				Class setParamType = getCLass(columnAnnotation.type());
				String setMethodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
				Method setMethod = c.getMethod(setMethodName, setParamType);
				setMethod.invoke(t, map.get(columnName));
			}
		}
		return t;
	}

	private Class<?> getCLass(int type) {
		switch (type) {
		case Types.INTEGER: return Integer.class;
		case Types.VARCHAR: return String.class;
		default : return Object.class;
		}
	}
	
}
